#include <stdio.h>      /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
#include <stdlib.h>     /* for atoi() and exit() */
#include <string.h>     /* for memset() */
#include <unistd.h>     /* for close() */
#include <time.h>

#define RCVBUFSIZE 1024   /* Size of receive buffer */

//void DieWithError(char *errorMessage);  /* Error handling function */

char intBuf[4];

int getInt(char *buf, int position) {
	for (int i=0; i<4; i++) {
		intBuf[i] = buf[position+3-i];
	}
	int msgType = *(reinterpret_cast<const int *>(intBuf));		
	return msgType;
}

void getIntArray(char *buf, int bpos, int *dest, int dpos, int length) {
	for (int i=0; i<length; i++) {
		dest[dpos + i] = getInt(buf, bpos + 4*i);
	}
}

void setInt(char *buf, int toAdd) {
	char* cmove = (char *)&toAdd;
	for (int i=0;i<4;i++) {
		buf[i] = cmove[3-i];
	}
}

void printGameState(int *gs, int numPlayers, int pIndx) {
	for (int i=0; i<numPlayers; i++) {
		if (i == pIndx) {
			printf("* ");
		} else {
			printf("  ");
		}
		for (int j=0; j<14; j++) {
			printf("%d ",gs[i*14 + j]);
		}
		printf("\n");
	}
}

void printHand(int *hand) {
	for (int i=0; i<5; i++) {
		printf(" %d",hand[i]);
	}
	printf("\n");
}

int calculateMove(int *gameState, int *hand, int messageType) {
	if (messageType <= 1) {
		return rand() % 31;
	} else if (messageType == 2) {
		return rand() % 13 + 1;
	} else {
		return -1;
	}
}

int main(int argc, char *argv[])
{
    int sock;                        /* Socket descriptor */
    struct sockaddr_in echoServAddr; /* Echo server address */
    unsigned short echoServPort;     /* Echo server port */
    char *servIP;                    /* Server IP address (dotted quad) */
    char *echoString;                /* String to send to echo server */
    char echoBuffer[RCVBUFSIZE];     /* Buffer for echo string */
    unsigned int echoStringLen;      /* Length of string to echo */
    int bytesRcvd, totalBytesRcvd;   /* Bytes read in single recv() 
                                        and total bytes read */
		int numPlayers;
		int playerIndx;
		int * gameState;
		int hand[5] = {-1};
		int shouldPause = 0;

		fprintf(stderr, "%d\n", argc);
    if (argc < 2)
    {
       fprintf(stderr, "Usage: [<Echo Port>]\n");
       exit(1);
    }

		if (argc == 3) {
			shouldPause = 1;
		}

    servIP = "127.0.0.1";
    echoServPort = atoi(argv[1]);

		/* Open connection for initialization */
    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        fprintf(stderr, "unable to initialize");
		}

    /* Construct the server address structure */
    memset(&echoServAddr, 0, sizeof(echoServAddr));     /* Zero out structure */
    echoServAddr.sin_family      = AF_INET;             /* Internet address family */
    echoServAddr.sin_addr.s_addr = inet_addr(servIP);   /* Server IP address */
    echoServAddr.sin_port        = htons(echoServPort); /* Server port */

    /* Establish the connection to the echo server */
		printf("connecting...");
    if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0) {
				printf("failed\n");
				exit(1);
		}
		printf("done\n");

		/* Get # of players & index */
		bytesRcvd = 0;
		if ( (bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0 ) {
			printf("Failed to receive player index and size of game\n");
			exit(1);
		}
		playerIndx = getInt(echoBuffer, 0);
		numPlayers = getInt(echoBuffer, 4);

		/* create game state */
		gameState = new int[numPlayers * 14];

		printf("Player %d of %d.\n", playerIndx, numPlayers);

		char buf[1024];
		srand( time(NULL) );
		int toMove = -1;
    while (1)
    {
       
				/* Receive State */
				bytesRcvd = 0;
				printf("receiving:");
        if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0) {
            printf(" FAILED\n");
						break;
				}
				printf(" %d bytes\n",bytesRcvd);
				
				//First 4 bytes are message type;
				int msgType = getInt(echoBuffer, 0);

				printf("Received a message of type %d\n", msgType);
				
				
				if (msgType <= 2) {
					getIntArray(echoBuffer,4,hand,0,5);
					if (msgType <= 1) {
						if (msgType == 0) {
							getIntArray(echoBuffer,24,gameState,0,numPlayers * 14);
							printGameState(gameState, numPlayers, playerIndx);
						}
						printHand(hand);
					} else {
						printHand(hand);
					}
				} else if (msgType == 99) {
					break;
				} else {
					printf("derf!\n");
				}
				
				int toMove = calculateMove(gameState, hand, msgType);

				//add move to the buffer
				setInt(buf,toMove);

				printf("sending %d\n", toMove);
        if ( send(sock,buf,4, 0) < 0 ) {
					fprintf(stderr,"failed\n");
				}

				if (shouldPause) {
					getchar();
				}
    }

    printf("\n");    /* Print a final linefeed */
		delete [] gameState;

    close(sock);
    exit(0);
}

